﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Drawing;

namespace DirectX_CS
{
	//displacement wave 3d or deltawave3d
	public class DWave3d : IManagedModelTransformable, IManagedVertexBuffer, IManagedMaterial, IColorable, IRangeModifiable
	{
		[PGBrowsable]
		public Range3d Range
		{
			get { return new Range3d(XMin, YMin, ZMin, XMax, YMax, ZMax); }
		}

		float mZMin = 0, mZMax = 10; //should be maximum and mimum of the function though... in the future.
		[PGBrowsable]
		public float ZMin
		{
			get { return mZMin; }
			set { mZMin = value; }
		}
		[PGBrowsable]
		public float ZMax
		{
			get { return mZMax; }
			set { mZMax = value; }
		}

		protected bool mEnableCallRenderPrimitives = true;
		[PGBrowsable]
		public bool EnableCallRenderPrimitives
		{
			get { return mEnableCallRenderPrimitives; }
			set { mEnableCallRenderPrimitives = value; }
		}
		protected bool mEnableCallRenderIndexedPrimitives = false;
		[PGBrowsable]
		public bool EnableCallRenderIndexedPrimitives
		{
			get { return mEnableCallRenderIndexedPrimitives; }
			set { mEnableCallRenderIndexedPrimitives = value; }
		}

		//public float Amplitude = .1f;
		[PGBrowsable]
		public float t = 0;
		private float tOffset = 0;
		private float MaxLifeTime = 20;
		[PGBrowsable]
		public float cx = 1f, cy = 1f, cz = 1f;
		[PGBrowsable]
		public float fx = 1f, fy = 1f, fz = 1f;

		protected Vector3 velocity;
		protected float rho = 1;
		protected float length;

		public float sqrt2PI = (float)Math.Sqrt(2 * Math.PI);
		protected bool mRegistered = false;

		public event VBChangedDelegate VertexBufferChanged;
		//public event IBChangedDelegate IndexBufferChanged;

		protected Material mMaterial;
		Color mVertexColor = Color.PowderBlue;
	
		Device mDxDevice = null;

		public Device DxDevice
		{
			get { return mDxDevice; }
			set { mDxDevice = value; }
		}
		public PrimitiveManager ManagedRenderer = null;
		[PGBrowsable]
		public Material Material
		{
			get { return mMaterial; }
			set { mMaterial = value; }
		}

		public DWave3d(Device dxDevice, PrimitiveManager managedRenderer)
		{
			mDxDevice = dxDevice;
			ManagedRenderer = managedRenderer;
			InitializeParticlePositions();
			Register();
			CreateVertexData();
		}
		public void Register()
		{
			PrimitiveManager.Register(this);
			mRegistered = true;
		}
		[PGBrowsable]
		public VertexFormats VertexFormat
		{
			get { return SVector.Format; }
		}
		public void ManagerDestroyed(PrimitiveManager caller)
		{
			ManagedRenderer = null;
		}

		private static float sin(double t)
		{
			return (float)Math.Sin(t);
		}
		private static float cos(double t)
		{
			return (float)Math.Cos(t);
		}
		//public float MaxValue = 0;
		[PGBrowsable]
		public Vector3 WavePosition
		{
			get { return velocity * t; }
		}
		
		Vector3[,] displacements = null;

		public void RenderPrimitives(PrimitiveManager renderer, int yourDataLength)
		{
			//draw just the vertex data as points
			mDxDevice.DrawPrimitives(PrimitiveType.PointList, 0, displacements.Length);
		}

		public void CalculateDisplacements()
		{
			Vector3 p = WavePosition;

			for (int xidx = 0; xidx < xCount; xidx++)
            {
				for (int yidx = 0; yidx < yCount; yidx++)
				{
						//EquilibriumPoint p = new EquilibriumPoint();
						//EquilibriumPoint p = displacements[xidx, yidx, zidx];
						float dx = 0;
						float dy = 0;
						float dz = 0;

						Vector3 d = new Vector3(0, 0, 0);
						displacements[xidx, yidx] = displacements[xidx, yidx] + d;
				}
            }
		}
		protected float zHeight;
		[PGBrowsable]
		public float ZHeight
		{
			get { return zHeight; }
			set { zHeight = value; }
		}

		protected float mTime = 0;
        ///SetTimedVertexData
        protected float dTime = .03f;

	   	private void InitializeParticlePositions()
		{
			displacements = new Vector3[xCount, yCount];

			for (int xidx = 0; xidx < xCount; xidx++)
			{
				for (int yidx = 0; yidx < yCount; yidx++)
				{
					float zHeight = ZHeight;
					Vector3 p = new Vector3(xidx * (xMax - xMin) + xMin, yidx * (yMax - yMin) + yMin, zHeight);
					displacements[xidx, yidx] += p;
				}
			}
		}


        private void CreateVertexData()
        {
			CalculateDisplacements();
            mVertexData = Flatten3dPoints();
        }


		//uses Vector[,] displacements
		Array Flatten3dPoints()	  
        {
            List<SVector> aData = new List<SVector>();
            //Color theColor = Color.Red;

            for (int xidx = 0; xidx < xCount; xidx++)
            {
                for (int yidx = 0; yidx < yCount; yidx++)
                {
                    SVector thePoint = new SVector(displacements[xidx, yidx]);
					thePoint.Color = MainVertexColor.ToArgb();
					aData.Add(thePoint);
                    //thePoint.Color = theColor.ToArgb();
                }
            }
            return aData.ToArray();
        }

		protected float hx = .5f;
		protected float hy = .5f;
		[PGBrowsable]
		public float hz = 1;
		[PGBrowsable]
		public float FrequencyX
		{
			get { return fx; }
			set { fx = value; }
		}
		[PGBrowsable]
		public float FrequencyY
		{
			get { return fy; }
			set { fy = value; }
		}
		[PGBrowsable]
		public float FrequencyZ
		{
			get { return fz; }
			set { fz = value; }
		}


		private float xMin = -10;
		[PGBrowsable]
		public float XMin
		{
			get { return xMin; }
			set { xMin = value; }
		}
		private float xMax = 10;
		[PGBrowsable]
		public float XMax
		{
			get { return xMax; }
			set { xMax = value; }
		}
		private int xCount = 10;
		[PGBrowsable]
		public int XCount
		{
			get { return xCount; }
			set { xCount = value; }
		}
		private float yMin = -10;
		[PGBrowsable]
		public float YMin
		{
			get { return yMin; }
			set { yMin = value; }
		}
		public float yMax = 10;
		[PGBrowsable]
		public float YMax
		{
			get { return yMax; }
			set { yMax = value; }
		}
		private int yCount = 10;
		[PGBrowsable]
		public int YCount
		{
			get { return yCount; }
			set { yCount = value; }
		}
		[PGBrowsable]
		public Vector3 Frequency
		{
			get { return new Vector3(fx, fy, fz); }
			set { fx = value.X; fy = value.Y; fz = value.Z; }
		}
		[PGBrowsable]
		public Color MainVertexColor
		{
			get { return mVertexColor; }
			set
			{
				mVertexColor = value;
			}
		}
		public void Recreate()
		{
			CreateVertexData();
			//CreateIndexData();

			VertexBufferChanged(this, mVertexData.Length); //as soon as its registered calls will probably start arriving.
			//IndexBufferChanged(this, mIndexData.Length); //as soon as its registered calls will probably start arriving.
		}
		public void UpdateTransform()
		{
			VertexBufferChanged(this, mVertexData.Length);
		}
		private TransformMatrix modelView = new TransformMatrix();
		[PGBrowsable]
		public TransformMatrix ModelView
		{
			get { return modelView; }
			set { modelView = value; }
		}

		//public delegate double PolarRT_ZFunc(double radius, double theta);

		protected Array mVertexData = null;

		public Array GetVertices()
		{
			return mVertexData;
		}
		public int GetVerticesCount()
		{
			return mVertexData == null ? 0 : mVertexData.Length;
		}
		private float yaw = 0;
		[PGBrowsable]
		public float Yaw
		{
			get { return yaw; }
			set { yaw = value; }
		}
		private float pitch = 0;
		[PGBrowsable]
		public float Pitch
		{
			get { return pitch; }
			set { pitch = value; }
		}
		private float roll = 0;
		[PGBrowsable]
		public float Roll
		{
			get { return roll; }
			set { roll = value; }
		}

	}
}
